home *** CD-ROM | disk | FTP | other *** search
- #-*-perl-*-
- # This is a wrapper to the chat2.pl routines that make life easier
- # to do ftp type work.
- # Mostly by Lee McLoughlin <lmjm@doc.ic.ac.uk>
- # based on original version by Alan R. Martello <al@ee.pitt.edu>
- # And by A.Macpherson@bnr.co.uk for multi-homed hosts
- #
- # Basic usage:
- # $ftp_port = 21;
- # $retry_call = 1;
- # $attempts = 2;
- # if( &ftp'open( $site, $ftp_port, $retry_call, $attempts ) != 1 ){
- # die "failed to open ftp connection";
- # }
- # if( ! &ftp'login( $user, $pass ) ){
- # die "failed to login";
- # }
- # &ftp'type( $text_mode ? 'A' : 'I' );
- # if( ! &ftp'get( $remote_filename, $local_filename, 0 ) ){
- # die "failed to get file;
- # }
- # &ftp'quit();
- #
- #
- # $Id: ftp.pl,v 2.4 1994/01/26 14:59:07 lmjm Exp lmjm $
- # $Log: ftp.pl,v $
- # Revision 2.4 1994/01/26 14:59:07 lmjm
- # Added DG result code.
- #
- # Revision 2.3 1994/01/18 21:58:18 lmjm
- # Reduce calls to sigset.
- # Reset to old signal after use.
- #
- # Revision 2.2 1993/12/14 11:09:06 lmjm
- # Use installed socket.ph.
- # Allow for more returns.
- #
- # Revision 2.1 1993/06/28 15:02:00 lmjm
- # Full 2.1 release
- #
- #
-
- require 'sys/socket.ph';
- require 'chat2.pl';
-
-
- package ftp;
-
- $retry_pause = 60; # Pause before retrying a login.
-
- if( defined( &main'PF_INET ) ){
- $pf_inet = &main'PF_INET;
- $sock_stream = &main'SOCK_STREAM;
- local($name, $aliases, $proto) = getprotobyname( 'tcp' );
- $tcp_proto = $proto;
- }
- else {
- # XXX hardwired $PF_INET, $SOCK_STREAM, 'tcp'
- # but who the heck would change these anyway? (:-)
- $pf_inet = 2;
- $sock_stream = 1;
- $tcp_proto = 6;
- }
-
- # If the remote ftp daemon doesn't respond within this time presume its dead
- # or something.
- $timeout = 120;
-
- # Timeout a read if I don't get data back within this many seconds
- $timeout_read = 3 * $timeout;
-
- # Timeout an open
- $timeout_open = $timeout;
-
- $ftp'version = '$Revision: 2.4 $';
-
- # This is a "global" it contains the last response from the remote ftp server
- # for use in error messages
- $ftp'response = "";
- # Also ftp'NS is the socket containing the data coming in from the remote ls
- # command.
-
- # The size of block to be read or written when talking to the remote
- # ftp server
- $ftp'ftpbufsize = 4096;
-
- # How often to print a hash out, when debugging
- $ftp'hashevery = 1024;
- # Output a newline after this many hashes to prevent outputing very long lines
- $ftp'hashnl = 70;
-
- # Is there a connection open?
- $ftp'service_open = 0;
-
- # If a proxy connection then who am I really talking to?
- $real_site = "";
-
- # Where error/log reports are sent to
- $ftp'showfd = 'STDERR';
-
- # Name of a function to call on a pathname to map it into a remote
- # pathname.
- $ftp'mapunixout = '';
- $ftp'manunixin = '';
-
- # This is just a tracing aid.
- $ftp_show = 0;
-
- sub ftp'debug
- {
- $ftp_show = @_[0];
- if( $ftp_show > 9 ){
- $chat'debug = 1;
- }
- }
-
- sub ftp'set_timeout
- {
- local( $to ) = @_;
- return if $to == $timeout;
- $timeout = $to;
- $timeout_open = $timeout;
- $timeout_read = 3 * $timeout;
- if( $ftp_show ){
- print $ftp'showfd "ftp timeout set to $timeout\n";
- }
- }
-
-
- sub ftp'open_alarm
- {
- die "timeout: open";
- }
-
- sub ftp'timed_open
- {
- local( $site, $ftp_port, $retry_call, $attempts ) = @_;
- local( $connect_site, $connect_port );
- local( $res );
-
- alarm( $timeout_open );
-
- while( $attempts-- ){
- if( $ftp_show ){
- print $ftp'showfd "proxy connecting via $proxy_gateway [$proxy_ftp_port]\n" if $proxy;
- print $ftp'showfd "Connecting to $site";
- if( $ftp_port != 21 ){
- print $ftp'showfd " [port $ftp_port]";
- }
- print $ftp'showfd "\n";
- }
-
- if( $proxy ) {
- if( ! $proxy_gateway ) {
- # if not otherwise set
- $proxy_gateway = "internet-gateway";
- }
- if( $debug ) {
- print $ftp'showfd "using proxy services of $proxy_gateway, ";
- print $ftp'showfd "at $proxy_ftp_port\n";
- }
- $connect_site = $proxy_gateway;
- $connect_port = $proxy_ftp_port;
- $real_site = $site;
- }
- else {
- $connect_site = $site;
- $connect_port = $ftp_port;
- }
- if( ! &chat'open_port( $connect_site, $connect_port ) ){
- if( $retry_call ){
- print $ftp'showfd "Failed to connect\n" if $ftp_show;
- next;
- }
- else {
- print $ftp'showfd "proxy connection failed " if $proxy;
- print $ftp'showfd "Cannot open ftp to $connect_site\n" if $ftp_show;
- return 0;
- }
- }
- $res = &ftp'expect( $timeout,
- 120, 0, # service unavailable to $site
- 220, 1, # ready for login to $site
- 421, 0); #service unavailable to $site closing connection
- if( ! $res ){
- &chat'close();
- next;
- }
- return 1;
- }
- continue {
- print $ftp'showfd "Pausing between retries\n";
- sleep( $retry_pause );
- }
- return 0;
- }
-
- sub main'ftp__sighandler
- {
- local( $sig ) = @_;
- local( $msg ) = "Caught a SIG$sig flagging connection down";
- $ftp'service_open = 0;
- if( $ftp_logger ){
- eval "&$ftp_logger( \$msg )";
- }
- }
-
- sub ftp'set_signals
- {
- $ftp_logger = @_;
- $SIG{ 'PIPE' } = "ftp__sighandler";
- }
-
- # Set the mapunixout and mapunixin functions
- sub ftp'set_namemap
- {
- ($ftp'mapunixout, $ftp'mapunixin) = @_;
- if( $debug ) {
- print $ftp'showfd "mapunixout = $ftp'mapunixout, $mapunixin = $ftp'mapunixin\n";
- }
- }
-
-
- sub ftp'open
- {
- local( $site, $ftp_port, $retry_call, $attempts ) = @_;
-
- local( $old_sig ) = $SIG{ 'ALRM' };
- $SIG{ 'ALRM' } = "ftp\'open_alarm";
-
- local( $ret ) = eval "&timed_open( '$site', $ftp_port, $retry_call, $attempts )";
- alarm( 0 );
- $SIG{ 'ALRM' } = $old_sig;
-
- if( $@ =~ /^timeout/ ){
- return -1;
- }
-
- if( $ret ){
- $ftp'service_open = 1;
- }
-
- return $ret;
- }
-
- sub ftp'login
- {
- local( $remote_user, $remote_password ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( $proxy ){
- &ftp'send( "USER $remote_user@$site" );
- }
- else {
- &ftp'send( "USER $remote_user" );
- }
- $ret = &ftp'expect( $timeout,
- 230, 1, # $remote_user logged in
- 331, 2, # send password for $remote_user
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 530, 0, # not logged in
- 332, 0, # account for login not supported
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- if( $ret == 1 ){
- # Logged in no password needed
- return 1;
- }
- elsif( $ret == 2 ){
- # A password is needed
- &ftp'send( "PASS $remote_password" );
-
- $ret = &ftp'expect( $timeout,
- 230, 1, # $remote_user logged in
-
- 202, 0, # command not implemented
- 332, 0, # account for login not supported
-
- 530, 0, # not logged in
- 500, 0, # syntax error
- 501, 0, # syntax error
- 503, 0, # bad sequence of commands
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- if( $ret == 1 ){
- # Logged in
- return 1;
- }
- }
- # If I got here I failed to login
- return 0;
- }
-
- sub service_closed
- {
- $ftp'service_open = 0;
- &chat'close();
- }
-
- sub ftp'close
- {
- &ftp'quit();
- $ftp'service_open = 0;
- &chat'close();
- }
-
- # Change directory
- # return 1 if successful
- # 0 on a failure
- sub ftp'cwd
- {
- local( $dir ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( $ftp'mapunixout ){
- $dir = eval "&$ftp'mapunixout( \$dir, 'd' )";
- }
-
- &ftp'send( "CWD $dir" );
-
- $ret = &ftp'expect( $timeout,
- 200, 1, # working directory = $dir
- 250, 1, # working directory = $dir
- 257, 1, # working directory = $dir
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 502, 0, # command not implemented
- 530, 0, # not logged in
- 550, 0, # cannot change directory
- 421, 99 ); # service unavailable, closing connection
-
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
-
- return $ret;
- }
-
- # Get a full directory listing:
- # &ftp'dir( remote LIST options )
- # Start a list going with the given options.
- # Presuming that the remote deamon uses the ls command to generate the
- # data to send back then then you can send it some extra options (eg: -lRa)
- # return 1 if sucessful and 0 on a failure
- sub ftp'dir_open
- {
- local( $options ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( ! &ftp'open_data_socket() ){
- return 0;
- }
-
- if( $options ){
- &ftp'send( "LIST $options" );
- }
- else {
- &ftp'send( "LIST" );
- }
-
- $ret = &ftp'expect( $timeout,
- 150, 1, # reading directory
-
- 125, 0, # data connection already open?
-
- 450, 0, # file unavailable
- 500, 0, # syntax error
- 501, 0, # syntax error
- 502, 0, # command not implemented
- 530, 0, # not logged in
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
-
- if( ! $ret ){
- &ftp'close_data_socket;
- return 0;
- }
-
- accept( NS, S ) || die "accept failed $!";
-
- #
- # the data should be coming at us now
- #
-
- return 1;
- }
-
-
- # Close down reading the result of a remote ls command
- # return 1 if successful and 0 on failure
- sub ftp'dir_close
- {
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- # read the close
- #
- $ret = &ftp'expect($timeout,
- 226, 1, # transfer complete, closing connection
- 250, 1, # action completed
-
- 425, 0, # can't open data connection
- 426, 0, # connection closed, transfer aborted
- 451, 0, # action aborted, local error
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
-
- # shut down our end of the socket
- &ftp'close_data_socket;
-
- if( ! $ret ){
- return 0;
- }
-
- return 1;
- }
-
- # Quit from the remote ftp server
- # return 1 if successful and 0 on failure
- sub ftp'quit
- {
- local( $ret );
-
- $site_command_check = 0;
- @site_command_list = ();
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- &ftp'send( "QUIT" );
-
- $ret = &ftp'expect( $timeout,
- 221, 1, # transfer complete, closing connection
- 500, 0, # error quitting??
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- return $ret;
- }
-
- # Support for ftp'read
- sub ftp'read_alarm
- {
- die "timeout: read";
- }
-
- # Support for ftp'read
- sub ftp'timed_read
- {
- alarm( $timeout_read );
-
- return sysread( NS, $ftpbuf, $ftpbufsize );
- }
-
- # Do not use this routing use ftp'get
- sub ftp'read
- {
- if( ! $ftp'service_open ){
- return -1;
- }
-
- local( $ret ) = eval '&timed_read()';
- alarm( 0 );
-
- if( $@ =~ /^timeout/ ){
- return -1;
- }
- return $ret;
- }
-
- # Get a remote file back into a local file.
- # If no loc_fname passed then uses rem_fname.
- # returns 1 on success and 0 on failure
- sub ftp'get
- {
- local($rem_fname, $loc_fname, $restart ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( $loc_fname eq "" ){
- $loc_fname = $rem_fname;
- }
-
- if( ! &ftp'open_data_socket() ){
- print $ftp'showfd "Cannot open data socket\n";
- return 0;
- }
-
- if( $loc_fname ne '-' ){
- # Find the size of the target file
- local( $restart_at ) = &ftp'filesize( $loc_fname );
- if( $restart && $restart_at > 0 && &ftp'restart( $restart_at ) ){
- $restart = 1;
- # Make sure the file can be updated
- chmod( 0644, $loc_fname );
- }
- else {
- $restart = 0;
- unlink( $loc_fname );
- }
- }
-
- if( $ftp'mapunixout ){
- $rem_fname = eval "&$ftp'mapunixout( \$rem_fname, 'f' )";
- }
-
- &ftp'send( "RETR $rem_fname" );
-
- $ret = &ftp'expect( $timeout,
- 150, 1, # receiving $rem_fname
-
- 125, 0, # data connection already open?
- 450, 2, # file unavailable
- 550, 2, # file unavailable
- 500, 0, # syntax error
- 501, 0, # syntax error
- 530, 0, # not logged in
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- if( $ret != 1 ){
- print $ftp'showfd "Failure on 'RETR $rem_fname' command\n";
-
- # shut down our end of the socket
- &ftp'close_data_socket;
-
- return 0;
- }
-
- accept( NS, S ) || die "accept failed $!";
-
- #
- # the data should be coming at us now
- #
-
- #
- # open the local fname
- # concatenate on the end if restarting, else just overwrite
- if( !open( FH, ($restart ? '>>' : '>') . $loc_fname ) ){
- print $ftp'showfd "Cannot create local file $loc_fname\n";
-
- # shut down our end of the socket
- &ftp'close_data_socket;
-
- return 0;
- }
-
- local( $start_time ) = time;
- local( $bytes, $lasthash, $hashes ) = (0, 0, 0);
- local( $old_sig ) = $SIG{ 'ALRM' };
- $SIG{ 'ALRM' } = "ftp\'read_alarm";
- while( ($len = &ftp'read()) > 0 ){
- $bytes += $len;
- if( $strip_cr ){
- $ftp'buf =~ s/\r//g;
- }
- if( $ftp_show ){
- while( $bytes > ($lasthash + $ftp'hashevery) ){
- print $ftp'showfd '#';
- $lasthash += $ftp'hashevery;
- $hashes++;
- if( ($hashes % $ftp'hashnl) == 0 ){
- print $ftp'showfd "\n";
- }
- }
- }
- if( ! print FH $ftp'ftpbuf ){
- print $ftp'showfd "\nfailed to write data";
- $bytes = -1;
- last;
- }
- }
- $SIG{ 'ALRM' } = $old_sig;
- close( FH );
-
- # shut down our end of the socket
- &ftp'close_data_socket;
-
- if( $len < 0 ){
- print $ftp'showfd "\ntimed out reading data!\n";
-
- return 0;
- }
-
- if( $ftp_show && $bytes > 0 ){
- if( $hashes && ($hashes % $ftp'hashnl) != 0 ){
- print $ftp'showfd "\n";
- }
- local( $secs ) = (time - $start_time);
- if( $secs <= 0 ){
- $secs = 1; # To avoid a divide by zero;
- }
-
- local( $rate ) = int( $bytes / $secs );
- print $ftp'showfd "Got $bytes bytes ($rate bytes/sec)\n";
- }
-
- #
- # read the close
- #
-
- $ret = &ftp'expect( $timeout,
- 226, 1, # transfer complete, closing connection
- 250, 1, # action completed
-
- 110, 0, # restart not supported
- 425, 0, # can't open data connection
- 426, 0, # connection closed, transfer aborted
- 451, 0, # action aborted, local error
- 550, 0, # permission denied
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
-
- if( $ret && $bytes < 0 ){
- $ret = 0;
- }
-
- return $ret;
- }
-
- sub ftp'delete
- {
- local( $rem_fname ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( $ftp'mapunixout ){
- $rem_fname = eval "&$ftp'mapunixout( \$rem_fname, 'f' )";
- }
-
- &ftp'send( "DELE $rem_fname" );
-
- $ret = &ftp'expect( $timeout,
- 250, 1, # Deleted $rem_fname
- 550, 0, # Permission denied
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
-
- return $ret == 1;
- }
-
- sub ftp'deldir
- {
- local( $fname ) = @_;
-
- # not yet implemented
- # RMD
- }
-
- # UPDATE ME!!!!!!
- # Add in the hash printing and newline conversion
- sub ftp'put
- {
- local( $loc_fname, $rem_fname ) = @_;
- local( $strip_cr );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( $loc_fname eq "" ){
- $loc_fname = $rem_fname;
- }
-
- if( ! &ftp'open_data_socket() ){
- return 0;
- }
-
- if( $ftp'mapunixout ){
- $rem_fname = eval "&$ftp'mapunixout( \$rem_fname, 'f' )";
- }
-
- &ftp'send( "STOR $rem_fname" );
-
- #
- # the data should be coming at us now
- #
-
- local( $ret ) =
- &ftp'expect( $timeout,
- 150, 1, # sending $loc_fname
-
- 125, 0, # data connection already open?
- 450, 0, # file unavailable
- 532, 0, # need account for storing files
- 452, 0, # insufficient storage on system
- 553, 0, # file name not allowed
- 500, 0, # syntax error
- 501, 0, # syntax error
- 530, 0, # not logged in
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
-
- if( $ret != 1 ){
- # shut down our end of the socket
- &ftp'close_data_socket;
-
- return 0;
- }
-
-
- accept( NS, S ) || die "accept failed $!";
-
- #
- # the data should be coming at us now
- #
-
- #
- # open the local fname
- #
- if( !open( FH, "<$loc_fname" ) ){
- print $ftp'showfd "Cannot open local file $loc_fname\n";
-
- # shut down our end of the socket
- &ftp'close_data_socket;
-
- return 0;
- }
-
- while( <FH> ){
- if( ! $ftp'service_open ){
- last;
- }
- print NS ;
- }
- close( FH );
-
- # shut down our end of the socket to signal EOF
- &ftp'close_data_socket;
-
- #
- # read the close
- #
-
- $ret = &ftp'expect( $timeout,
- 226, 1, # transfer complete, closing connection
- 250, 1, # action completed
-
- 110, 0, # restart not supported
- 425, 0, # can't open data connection
- 426, 0, # connection closed, transfer aborted
- 451, 0, # action aborted, local error
- 551, 0, # page type unknown
- 552, 0, # storage allocation exceeded
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- if( ! $ret ){
- print $ftp'showfd "Failure on 'STOR $loc_fname' command\n";
- }
- return $ret;
- }
-
- sub ftp'restart
- {
- local( $restart_point, $ret ) = @_;
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- &ftp'send( "REST $restart_point" );
-
- #
- # see what they say
-
- $ret = &ftp'expect( $timeout,
- 350, 1, # restarting at $restart_point
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 502, 2, # REST not implemented
- 530, 0, # not logged in
- 545, 2, # REST not implemented
- 554, 2, # REST not implemented
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- return $ret;
- }
-
- # Set the file transfer type
- sub ftp'type
- {
- local( $type ) = @_;
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- &ftp'send( "TYPE $type" );
-
- #
- # see what they say
-
- $ret = &ftp'expect( $timeout,
- 200, 1, # file type set to $type
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 504, 0, # Invalid form or byte size for type $type
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- return $ret;
- }
-
- $site_command_check = 0;
- @site_command_list = ();
-
- # routine to query the remote server for 'SITE' commands supported
- sub ftp'site_commands
- {
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- # if we havent sent a 'HELP SITE', send it now
- if( !$site_command_check ){
-
- $site_command_check = 1;
-
- &ftp'send( "HELP SITE" );
-
- # assume the line in the HELP SITE response with the 'HELP'
- # command is the one for us
- $ret = &ftp'expect( $timeout,
- ".*HELP.*", "\$1",
- 214, "0",
- 202, "0",
- 421, "99" ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = "0";
- }
-
- if( $ret eq "0" ){
- print $ftp'showfd "No response from HELP SITE\n" if( $ftp_show );
- }
-
- @site_command_list = split(/\s+/, $ret);
- }
-
- return @site_command_list;
- }
-
- # return the pwd, or null if we can't get the pwd
- sub ftp'pwd
- {
- local( $ret, $cwd );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- &ftp'send( "PWD" );
-
- #
- # see what they say
-
- $ret = &ftp'expect( $timeout,
- 257, 1, # working dir is
- 500, 0, # syntax error
- 501, 0, # syntax error
- 502, 0, # PWD not implemented
- 550, 0, # file unavailable
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- if( $ret ){
- if( $ftp'response =~ /^257\s"(.*)"\s.*$/ ){
- $cwd = $1;
- }
- }
- return $cwd;
- }
-
- # return 1 for success, 0 for failure
- sub ftp'mkdir
- {
- local( $path ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( $ftp'mapunixout ){
- $path = eval "&$ftp'mapunixout( \$path, 'f' )";
- }
-
- &ftp'send( "MKD $path" );
-
- #
- # see what they say
-
- $ret = &ftp'expect( $timeout,
- 257, 1, # made directory $path
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 502, 0, # MKD not implemented
- 530, 0, # not logged in
- 550, 0, # file unavailable
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- return $ret;
- }
-
- # return 1 for success, 0 for failure
- sub ftp'chmod
- {
- local( $path, $mode ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( $ftp'mapunixout ){
- $path = eval "&$ftp'mapunixout( \$path, 'f' )";
- }
-
- &ftp'send( sprintf( "SITE CHMOD %o $path", $mode ) );
-
- #
- # see what they say
-
- $ret = &ftp'expect( $timeout,
- 200, 1, # chmod $mode $path succeeded
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 502, 0, # CHMOD not implemented
- 530, 0, # not logged in
- 550, 0, # file unavailable
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- return $ret;
- }
-
- # rename a file
- sub ftp'rename
- {
- local( $old_name, $new_name ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- if( $ftp'mapunixout ){
- $old_name = eval "&$ftp'mapunixout( \$old_name, 'f' )";
- }
-
- &ftp'send( "RNFR $old_name" );
-
- #
- # see what they say
-
- $ret = &ftp'expect( $timeout,
- 350, 1, # OK
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 502, 0, # RNFR not implemented
- 530, 0, # not logged in
- 550, 0, # file unavailable
- 450, 0, # file unavailable
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
-
- # check if the "rename from" occurred ok
- if( $ret ){
- if( $ftp'mapunixout ){
- $new_name = eval "&$ftp'mapunixout( \$new_name, 'f' )";
- }
-
- &ftp'send( "RNTO $new_name" );
-
- #
- # see what they say
-
- $ret = &ftp'expect( $timeout,
- 250, 1, # rename $old_name to $new_name
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 502, 0, # RNTO not implemented
- 503, 0, # bad sequence of commands
- 530, 0, # not logged in
- 532, 0, # need account for storing files
- 553, 0, # file name not allowed
-
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- }
-
- return $ret;
- }
-
-
- sub ftp'quote
- {
- local( $cmd ) = @_;
- local( $ret );
-
- if( ! $ftp'service_open ){
- return 0;
- }
-
- &ftp'send( $cmd );
-
- $ret = &ftp'expect( $timeout,
- 200, 1, # Remote '$cmd' OK
- 500, 0, # error in remote '$cmd'
- 421, 99 ); # service unavailable, closing connection
- if( $ret == 99 ){
- &service_closed();
- $ret = 0;
- }
- return $ret;
- }
-
- # ------------------------------------------------------------------------------
- # These are the lower level support routines
-
- sub ftp'expectgot
- {
- ($ftp'response, $ftp'fatalerror) = @_;
- if( $ftp_show ){
- print $ftp'showfd "$ftp'response\n";
- }
- }
-
- #
- # create the list of parameters for chat'expect
- #
- # ftp'expect(time_out, {value, return value});
- # the last response is stored in $ftp'response
- #
- sub ftp'expect
- {
- local( $ret );
- local( $time_out );
- local( @expect_args );
- local( $code, $pre );
-
- $ftp'response = '';
- $ftp'fatalerror = 0;
-
- $time_out = shift( @_ );
-
- while( @_ ){
- $code = shift( @_ );
- $pre = '^';
- if( $code =~ /^\d+$/ ){
- $pre = "[.|\n]*^";
- }
- push( @expect_args, "$pre(" . $code . " .*)\\015\\n" );
- push( @expect_args,
- "&expectgot( \$1, 0 ); " . shift( @_ ) );
- }
-
- # Treat all unrecognised lines as continuations
- push( @expect_args, "^(.*)\\015\\n" );
- push( @expect_args, "&expectgot( \$1, 0 ); 100" );
-
- # add patterns TIMEOUT and EOF
-
- push( @expect_args, 'TIMEOUT' );
- push( @expect_args, "&expectgot( 'timed out', 0 ); 0" );
-
- push( @expect_args, 'EOF' );
- push( @expect_args, "&expectgot( 'remote server gone away', 1 ); 99" );
-
- if( $ftp_show > 9 ){
- &printargs( $time_out, @expect_args );
- }
-
- $ret = &chat'expect( $time_out, @expect_args );
- if( $ret == 100 ){
- # we saw a continuation line, wait for the end
- push( @expect_args, "^.*\n" );
- push( @expect_args, "100" );
-
- while( $ret == 100 ){
- if( $ftp_show > 9 ){
- &printargs( $time_out, @expect_args );
- }
- $ret = &chat'expect( $time_out, @expect_args );
- }
- }
-
- return $ret;
- }
-
-
- #
- # opens NS for io
- #
- sub ftp'open_data_socket
- {
- local( $sockaddr, $port );
- local( $type, $myaddr, $a, $b, $c, $d );
- local( $mysockaddr, $family, $hi, $lo );
-
- $sockaddr = 'S n a4 x8';
-
- ($a,$b,$c,$d) = unpack( 'C4', $chat'thisaddr );
- $this = $chat'thisproc;
-
- socket( S, $pf_inet, $sock_stream, $tcp_proto ) || die "socket: $!";
- bind( S, $this ) || die "bind: $!";
-
- # get the port number
- $mysockaddr = getsockname( S );
- ($family, $port, $myaddr) = unpack( $sockaddr, $mysockaddr );
-
- $hi = ($port >> 8) & 0x00ff;
- $lo = $port & 0x00ff;
-
- #
- # we MUST do a listen before sending the port otherwise
- # the PORT may fail
- #
- listen( S, 5 ) || die "listen";
-
- &ftp'send( "PORT $a,$b,$c,$d,$hi,$lo" );
-
- return &ftp'expect($timeout,
- 200, 1, # PORT command successful
- 250, 1, # PORT command successful
-
- 500, 0, # syntax error
- 501, 0, # syntax error
- 530, 0, # not logged in
-
- 421, 0); # service unavailable, closing connection
- }
-
- sub ftp'close_data_socket
- {
- close( NS );
- }
-
- sub ftp'send
- {
- local( $send_cmd ) = @_;
-
- if( $send_cmd =~ /\n/ ){
- print $ftp'showfd "ERROR, \\n in send string for $send_cmd\n";
- }
-
- if( $ftp_show ){
- local( $sc ) = $send_cmd;
-
- if( $send_cmd =~ /^PASS/){
- $sc = "PASS <somestring>";
- }
- print $ftp'showfd "---> $sc\n";
- }
-
- &chat'print( "$send_cmd\r\n" );
- }
-
- sub ftp'printargs
- {
- while( @_ ){
- print $ftp'showfd shift( @_ ) . "\n";
- }
- }
-
- sub ftp'filesize
- {
- local( $fname ) = @_;
-
- if( ! -f $fname ){
- return -1;
- }
-
- return (stat( _ ))[ 7 ];
-
- }
-
- # make this package return true
- 1;
-